#include "datastruct.h"
#include <netdb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
char *file = NULL;

//保活线程
void *keep_live(void *arg)
{
	int sockfd = *(int *)arg;
	Message live;
	live.type = KEEPLIVE;
	time_t now = time(NULL);
	live.time = now;
	send(sockfd, &live, sizeof(live), 0);
	sleep(60);
	return 0;
}
//接收文件线程
void *recv_file(void *arg)
{
	struct sockaddr_in my_addr = *(struct sockaddr_in *)arg;	
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
		err_sys("socket error");
	int sockopt = 1;
	if((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt))) < 0)
		err_sys("setsockopt error");
	int ret;
	ret = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
	if(ret != 0)
		err_sys("bind error");
	//监听
	ret = listen(sockfd, 5);
	if(ret != 0)
		err_sys("listen error");
	printf("listening ...\n");
	
	struct sockaddr_in client_addr;
	char client_ip[INET_ADDRSTRLEN] = {0};
	socklen_t cliaddr_len = sizeof(client_addr);
	//连接
	int connfd;
	connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
	if(connfd < 0)
		err_sys("accept error");
	inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
	printf("client ip: %s, port: %d\n", client_ip, ntohs(client_addr.sin_port));
	
	//接收文件
	int fd = open("ds.c", O_WRONLY|O_CREAT|O_TRUNC, 0755);
	if(fd < 0)
		err_sys("recv_open error");
	char buffer[1024] = {0};
	//接收数据写入文件
	printf("recv file\n");
	int n = recv(connfd, buffer, 1024, 0);
	while(n != 0)
	{
		n = recv(connfd, buffer, 1024, 0);
		printf("%s\n",buffer);
		write(fd, buffer, strlen(buffer));
	}
	close(fd);
	close(connfd);
	close(sockfd);
	return NULL;
}
//发送文件线程
void *send_file(void *arg)
{
	struct sockaddr_in dst_addr = *(struct sockaddr_in *)arg;
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
		err_sys("socket error");
	//发起connect操作
	int ret;
	ret = connect(sockfd, (struct sockaddr*)&dst_addr, sizeof(dst_addr));
	if(ret != 0)
		err_sys("connect error");
	//创建文件
	char file_name[20] ={0};
	printf("please input file name\n");
	scanf("%s",file_name);
	int fd = open(file_name, O_RDONLY);
	if(fd < 0)
		err_sys("send_open error");
	//发送数据
	printf("send file\n");
	char buffer[1024] = {0};
	int n = read(fd, buffer, 1024);
	while(n != 0) 
	{		
		n = read(fd, buffer, 1024);
		printf("%s\n",buffer);
		send(sockfd, buffer, strlen(buffer), 0);
		sleep(1);
	}
	close(fd);
	sleep(2);
	close(sockfd);
	return NULL;
}
int main()
{
	//创建套接字
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
		err_sys("socket error");

	//指定connect地址
	struct sockaddr_in dst_addr;
	bzero(&dst_addr, sizeof(dst_addr));
	dst_addr.sin_family = AF_INET;
	dst_addr.sin_port = htons(9999);
	inet_pton(AF_INET, "127.0.0.1", &dst_addr.sin_addr);

	//发起connect操作
	int ret;
	ret = connect(sockfd, (struct sockaddr*)&dst_addr, sizeof(dst_addr));
	if(ret != 0)
		err_sys("connect error");
	
	char buf[1024] = {0};
	//注册
	Message user;
	do
	{
		bzero(buf, sizeof(buf));
		user.type = REGISTER;
		time_t now = time(NULL);
		user.time = now;
		fgets(user.fromuser, 20, stdin);
		send(sockfd, &user, sizeof(user), 0);
		ret = recv(sockfd, buf, 1024, 0);
		if(ret == -1)
			err_sys("recv error!");
		printf("%s\n", buf);
	}while(strncmp(buf, "Success", strlen("Success")!=0));
	//获取当前在线用户
	Message get_user;
	printf("Do you want to get online user:Yes or No\n");
	get_user.type = GETUSER;
	fgets(get_user.data, 1024, stdin);
	if(strncmp(get_user.data, "Yes", strlen("Yes")) == 0)
	{
		send(sockfd, &get_user, sizeof(get_user), 0);
		char user_buf[1024]={0};
		ret = recv(sockfd, user_buf, sizeof(user_buf), 0);
		if(ret == -1)
			err_sys("recv error!");
		printf("%s\n", user_buf);
	}
	//读写
	Message send_msg;
	Message recv_msg;
	
	//终端输入停止标志
	int stdineof = 0;
	int maxfd = sockfd + 1;
	fd_set read_set;
	FD_ZERO(&read_set);
	pthread_t tid;
	ret = pthread_create(&tid, NULL, keep_live, (void *)&sockfd);
	if(ret != 0)
		err_sys("pthread_create error");
	pthread_detach(tid);
	while(1)
	{
		if(stdineof == 0)
		{
			FD_SET(0, &read_set);
		}
		FD_SET(sockfd, &read_set);
		printf("Now You can receive data or enter touser\n");	
		select(maxfd, &read_set, NULL, NULL, NULL);
		
		if(FD_ISSET(0, &read_set))
		{
			//发送			
			bzero(&send_msg, sizeof(send_msg));
			send_msg.type = DATA;
			strcpy(send_msg.fromuser, user.fromuser);
			time_t now = time(NULL);
			send_msg.time = now;
			
			fgets(send_msg.touser, 20, stdin);
			printf("Please input message:\n");
			fgets(send_msg.data, 1024, stdin);			
			if(strncmp(send_msg.data, "stop", strlen("stop")) == 0)
			{
				stdineof = 1;
				shutdown(sockfd, SHUT_WR);
				FD_CLR(0, &read_set);
				continue;
			}			
			send(sockfd, &send_msg, sizeof(send_msg), 0);
		}
		if(FD_ISSET(sockfd, &read_set))
		{
			//接收 
			
			char buff[20] = {0};
			ret = recv(sockfd, &recv_msg, sizeof(recv_msg), 0);
			if(ret == 0)
			{
				printf("server closed!\n");
				break;		
			}
			else if(ret == -1)
			{
				err_sys("recv error");
			}
			else
			{
				if(recv_msg.type == DATA)
				{
					char buf[9] = {0};
					strncpy(buf, recv_msg.data, 8);
					//接收发送文件请求
					//接收数据格式[SENFILE 文件名]
					if(strncmp(buf, "SENDFILE", strlen("SENDFILE")) == 0)
					{
						printf("user:%s\n",recv_msg.fromuser);
						char *str = ctime(&recv_msg.time);
						printf("time:%s\n", str);
						printf("message:%s\n", recv_msg.data);	
						file = (char *)(recv_msg.data + 9);
						int n = rand()%1000;
						n = n + 8000;
						struct sockaddr_in my_addr;
						bzero(&my_addr, sizeof(my_addr));
						my_addr.sin_family = AF_INET;
						my_addr.sin_port = htons(n);
						my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
						
						Message buff;
						buff.type = DATA;
						
						char src_ip[32] = "";
						inet_ntop(AF_INET, &(my_addr.sin_addr.s_addr), src_ip, 32);
						char buf[1024]={0};					
						sprintf(buf,"ACCEPTFD port: %d", n);
						strcpy(buff.data, buf);
						bzero(buf, strlen(buf));
						sprintf(buf," IP: %s", src_ip);
						strcat(buff.data, buf);
						printf("%s\n", buff.data);
						buff.type = DATA;
						strcpy(buff.fromuser, user.fromuser);
						strcpy(buff.touser, recv_msg.fromuser);
						send(sockfd, &buff, sizeof(buff), 0);
						pthread_t tid;
						pthread_create(&tid, NULL, (void *)recv_file, (void *)&my_addr);
						pthread_detach(tid);
					}
					//接收同意发送文件
					else if(strncmp(buf, "ACCEPTFD", strlen("ACCEPTFD")) == 0)
					{			
						printf("user:%s\n",recv_msg.fromuser);
						char *str = ctime(&recv_msg.time);
						printf("time:%s\n", str);
						printf("message:%s\n", recv_msg.data);	
						//指定connect地址
						//接收到的数据格式[ACCEPTFD port : xxxx IP: xxxxx]
						int n = 0;
						int j = 15;
						while(j < 19)
						{
							n = ((recv_msg.data[j++]) - '0') + n * 10;
						}
						printf("%d\n",n);
					//	char *p =(char *)(recv_msg.data + 24);
						struct sockaddr_in dst_addr;
						bzero(&dst_addr, sizeof(dst_addr));
						dst_addr.sin_family = AF_INET;
						dst_addr.sin_port = htons(n);
					//	inet_pton(AF_INET, p, &dst_addr.sin_addr);
						inet_pton(AF_INET, "127.0.0.1", &dst_addr.sin_addr);
						sleep(1);
						pthread_t tid;
						pthread_create(&tid, NULL, (void *)send_file, (void *)&dst_addr);
						pthread_join(tid,NULL);
					}
					else
					{
						printf("user:%s\n",recv_msg.fromuser);
						char *str = ctime(&recv_msg.time);
						printf("time:%s\n", str);
						printf("message:%s\n", recv_msg.data);	
					}
				}
				bzero(&recv_msg, sizeof(recv_msg));
				bzero(buff, strlen(buff));
			}
		}
	}
	close(sockfd);
	return 0;
}